package ControlLayer;

import java.util.ArrayList;
import java.lang.StringBuilder;
import ModelLayer.*;
/**
 * This class is part of an address book system. It functions as a controller for the AddressBook class in
 * the ModelLayer. Any changes to AddressBook or Person classes will go through this class.
 * This class is used through the system UI, more specifically AddressBookUI.
 *
 * @author Anders A.P., Anna K., Danny M.P., Jakob K., Mie P.  
 * @version 1.1
 *          1.1 update:     Made changes to updatePerson(), to avoid the loss of references between classes. 
 *                          This method now updates properly the fields contained within the class itself. 
 *                         
 *                          Made changes to deletePerson(), requiring the method to return a boolean value.
 *                          This method now provides proper logic when used in other methods.    
 */
public class AddressCtr
{   
    private AddressBook addrCon; 

    /**
     * Constructs an instance of class AddressCtr, taking no parameters. Takes an instance of the singleton class AddressBook.
     */
    public AddressCtr()
    {
        addrCon = addrCon.getInstance();
    }

    /**
     * Finds an object of class Person, taking the follow parameter:
     *
     * @param   id          Person objects ID, using this as a key in the HashMap addrCon.
     * @return  String      Returns a String object containing Person object's field values constructed using a StringBuilder object.
     * @throw   Exception   If ID is invalid.
     */
    public String findPersonID(String id)
    {
        StringBuilder stringBuilder = new StringBuilder();
        if (!validID(id)) {
            throw new IllegalArgumentException("invalid ID");
        }
        else {
            Person p = addrCon.getPersonID(id);
            stringBuilder.append("\n" + p.getName()+ "\n" + 
                p.getID() + "\n" + 
                p.getAddress() + "\n" + 
                p.getPostalCode() + "\n" + 
                p.getCity() + "\n" + 
                p.getPhone()); 
        }
        return stringBuilder.toString();
    }

    /**
     * Returns an object of class Person to the caller, using object's ID as key in the HashMap addrCon.
     *
     * @param   id          The key used to find the mapping in the HashMap addrCon.
     * @return  Person      Returns an object of class Person, mapped with the key ID.
     * @throw   Exception   If ID is invalid. 
     */
    public Person findLoaner(String id)
    {
        if (validID(id)) {
            return addrCon.getPersonID(id);
        }
        else {
            throw new IllegalArgumentException("invalid ID");
        }            
    }

    /**
     * Performs a check to see if ID is valid.
     * 
     * @param   id      Person id in form of a String
     * @return  false   If id is null or shorter than 1 character
     * @return  true    If id is not null or min 1 chracter
     */
    private boolean validID(String id)
    {
        if (id != null && id.length() >= 1) {
            return true;
        }
        return false;
    }

    /**
     * Finds a person in the HashMap by Person name.
     *
     * @param   name    The name used to find the Person object.
     * @return  String  Returns a String object containing Person object's field values constructed using a StringBuilder object.
     */
    public String findPersonName(String name)
    {
        ArrayList<Person> pList = addrCon.getPersonName(name);
        StringBuilder stringBuilder = new StringBuilder();        
        if (pList.size() == 0) {
            throw new IllegalArgumentException("Name not found");
        }
        else {            
            for(Person p : pList) {
                stringBuilder.append("\n" + p.getID() + "\n" + 
                                     p.getName() + "\n" + 
                                     p.getAddress() + "\n" + 
                                     p.getPostalCode() + "\n" + 
                                     p.getCity() + "\n" + 
                                     p.getPhone());
            }
        }
        return stringBuilder.toString();
    }

    /**
     * Creates a Person object and stores it in the container.
     * 
     * @param   id          Person ID. 
     * @param   name        Person name. 
     * @param   address     Person address.
     * @param   postalCode  Part of address, postal code.  
     * @param   city        Part of address, city.
     * @param   phone       Person phone number.
     * @throw   Exception   If ID is already in use (Meaning Person has already been created).
     */
    public void createPerson(String id, String name, String address, String postalCode, String city, String phone)
    {   
        ArrayList<Person> persons = addrCon.listAll();
        for(Person p : persons) {
            if(p.getID().equals(id)) {
                throw new IllegalArgumentException("ID is allready taken");
            }
        }
        Person p = new Person(id, name, address, postalCode, city, phone);
        addrCon.addPerson(p); 
    }

    /**
     * Removes a person from the collection using id as a key.
     * 
     * @param   id      ID of the person to be removed.
     * @return  false   If person has not been deleted from the collection.
     * @return  true    If person has been deleted from the collection.
     */
    public boolean deletePerson(String id)
    {
        return addrCon.deletePerson(id);
    }

    /**
     * Finds a Person object by ID, then proceeds to update the information about the person.
     * 
     * @param   id          Person ID. 
     * @param   name        Person name. 
     * @param   address     Person address.
     * @param   postalCode  Part of address, postal code.  
     * @param   city        Part of address, city.
     * @param   phone       Person phone number.
     * @throw   Exception   If ID is not found.
     */
    public void updatePerson(String id, String name, String address, String postalCode, String city, String phone)
    {
        if(validID(id)) {
            Person p = findLoaner(id);
            p.setName(name);
            p.setAddress(address, postalCode, city);
            p.setPhone(phone);
        }
        else {
            throw new IllegalArgumentException ("ID not found, update failed.");
        }
    }

    /**
     * Returns a list of all Person objects contained in the collection.
     *
     * @return  String  A list of all persons in the AddressBook collection.
     */
    public String listAllPersons()
    {
        StringBuilder stringBuilder = new StringBuilder();
        ArrayList<Person> persons = addrCon.listAll();
        if (persons.size() != 0) {
            for (Person p : persons) {
                stringBuilder.append("\n" + 
                                     p.getID() + "\n" + 
                                     p.getName() + "\n" + 
                                     p.getAddress() + "\n" + 
                                     p.getPostalCode() + "\n" + 
                                     p.getCity() + "\n" + 
                                     p.getPhone() + "\n");
            }
            return stringBuilder.toString();
        }
        return null;
    }
}
